#include "YaRRIncludes.h"


/************************************** Polite Request ***************************************
** I have put a lot of time and effort into YaRR. If you want to use some of the source     **
** please tell me. Anything used from YaRR must be open source, as is scripts.dll.          **
***************************************** Thank you *****************************************/


void YaRRVeteran::Startup()
{
	DLOG;
}

void YaRRVeteran::Shutdown()
{
	DLOG;
}

void YaRRVeteran::Kill(GameObject *Killed, int ID)
{
	DLOG;
	const char *PName = Get_Player_Name_By_ID(ID);
	GameObject *PObj = Get_Vehicle(Get_GameObj(ID));
	if(!PObj)
	{
		PObj = Get_GameObj(ID);
	}
	
	const char *pscreenname = GetPresetScreenName(PObj);

	int Type = 1;
	if(Is_Building(Killed))
	{
		Type = 0;
	}
	else if(Is_Vehicle(Killed))
	{
		Type = 1;
	}
	else if(Is_Soldier(Killed))
	{
		Type = 2;
	}
	Stacker<Row *> Result;
	Query(&Result, "SELECT * FROM PresetKills WHERE Nick = '%q' AND Preset = '%q';", PName, Commands->Get_Preset_Name(PObj));
	if(Result.Empty())
	{
		Query(0, "INSERT INTO PresetKills(Nick, Preset, PresetReadName, Type, Purchased, Kills, VehicleDestroyed, BuildingsDestroyed, DestroyedVehicle, DestroyedSoldier, DestroyedBuilding) VALUES('%q', '%q', '%q', %d, %d, %d, %d, %d, %d, %d, %d);", PName, Commands->Get_Preset_Name(PObj), pscreenname, Type, 0, 0, 0, 0, 0, 0, 0);
	}
	DeleteResult(&Result);

	int KS = (Type == 2 ? 1 : 0);
	int KV = (Type == 1 ? 1 : 0);
	int KB = (Type == 0 ? 1 : 0);

	Query(0, "UPDATE PresetKills SET Kills = Kills + %d, VehicleDestroyed = VehicleDestroyed + %d, BuildingsDestroyed = BuildingsDestroyed + %d WHERE Nick = '%q' AND Preset = '%q';", KS, KV, KB, PName, Commands->Get_Preset_Name(PObj));	
	delete []PName;
	CDealloc(pscreenname);
}

void YaRRVeteran::Killed(GameObject *Killer, int ID)
{
	DLOG;
	const char *PName = Get_Player_Name_By_ID(ID);
	GameObject *PObj = Get_Vehicle(Get_GameObj(ID));
	if(!PObj)
	{
		PObj = Get_GameObj(ID);
	}
	
	const char *pscreenname = GetPresetScreenName(PObj);

	int Type = 1;
	if(Is_Building(Killer))
	{
		Type = 0;
	}
	else if(Is_Vehicle(Killer))
	{
		Type = 1;
	}
	else if(Is_Soldier(Killer))
	{
		Type = 2;
	}
	Stacker<Row *> Result;
	Query(&Result, "SELECT * FROM PresetKills WHERE Nick = '%q' AND Preset = '%q';", PName, Commands->Get_Preset_Name(PObj));
	if(Result.Empty())
	{
		Query(0, "INSERT INTO PresetKills(Nick, Preset, PresetReadName, Type, Purchased, Kills, VehicleDestroyed, BuildingsDestroyed, DestroyedVehicle, DestroyedSoldier, DestroyedBuilding) VALUES('%q', '%q', '%q', %d, %d, %d, %d, %d, %d, %d, %d);", PName, Commands->Get_Preset_Name(PObj), pscreenname, Type, 0, 0, 0, 0, 0, 0, 0);
	}
	DeleteResult(&Result);

	int KS = (Type == 2 ? 1 : 0);
	int KV = (Type == 1 ? 1 : 0);
	int KB = (Type == 0 ? 1 : 0);

	Query(0, "UPDATE PresetKills SET DestroyedSoldier = DestroyedSoldier+%d, DestroyedVehicle = DestroyedVehicle + %d, DestroyedBuilding = DestroyedBuilding + %d WHERE Nick = '%q' AND Preset = '%q';", KS, KV, KB, PName, Commands->Get_Preset_Name(PObj));	
	delete []PName;
	CDealloc(pscreenname);
}

void YaRRVeteran::Purchased(const char *Preset, int Type, int ID)
{
	DLOG;
	const char *PName = Get_Player_Name_By_ID(ID);
	const char *pscreenname = GetPresetScreenName(Preset);

	Stacker<Row *> Result;
	Query(&Result, "SELECT * FROM PresetKills WHERE Nick = '%q' AND Preset = '%q';", PName, Preset);
	if(Result.Empty())
	{
		Query(0, "INSERT INTO PresetKills(Nick, Preset, PresetReadName, Type, Purchased, Kills, VehicleDestroyed, BuildingsDestroyed, DestroyedVehicle, DestroyedSoldier, DestroyedBuilding) VALUES('%q', '%q', '%q', %d, 0, 0, 0, 0, 0, 0, 0);", PName, Preset, pscreenname, Type);
	}
	DeleteResult(&Result);

	Query(0, "UPDATE PresetKills SET Purchased = Purchased+1 WHERE Nick = '%q' AND Preset = '%q';", PName, Preset);	
	delete []PName;
	CDealloc(pscreenname);
}

void YaRRVeteran::Think()
{
	DLOG;
	for(int i = 0; i < 127; i++)
	{
		Player *p = Players[i];
		if(p)
		{
			if(YaRRSettings::Medals::Killer_Threshold != 0)
			{
				int Killer_Threshold = (p->Rank.Killer_Medals+1)*YaRRSettings::Medals::Killer_Threshold;
				if(Killer_Threshold <= p->Rank.Player_Kills)
				{
					YaRRVeteran::GiveMedal(p, 1);
				}
			}

			if(YaRRSettings::Medals::ArmsDestroyer_Threshold != 0)
			{
				int ArmsDestroyer_Threshold = (p->Rank.ArmsDestroyer_Medals+1)*YaRRSettings::Medals::ArmsDestroyer_Threshold;
				if(ArmsDestroyer_Threshold <= p->Rank.LightVehicle_Kills)
				{
					YaRRVeteran::GiveMedal(p, 2);
				}
			}

			if(YaRRSettings::Medals::ArmorDestroyer_Threshold != 0)
			{
				int ArmorDestroyer_Threshold = (p->Rank.ArmorDestroyer_Medals+1)*YaRRSettings::Medals::ArmorDestroyer_Threshold;
				if(ArmorDestroyer_Threshold <= p->Rank.HeavyVehicle_Kills)
				{
					YaRRVeteran::GiveMedal(p, 3);
				}
			}

			if(YaRRSettings::Medals::Demolition_Threshold != 0)
			{
				int Demolition_Threshold = (p->Rank.Demolition_Medals+1)*YaRRSettings::Medals::Demolition_Threshold;
				if(Demolition_Threshold <= p->Rank.Building_Kills)
				{
					YaRRVeteran::GiveMedal(p, 4);
				}
			}

			if(YaRRSettings::Medals::Sabatage_Threshold != 0)
			{
				int Sabatage_Threshold = (p->Rank.Sabatage_Medals+1)*YaRRSettings::Medals::Sabatage_Threshold;
				if(Sabatage_Threshold <= p->Rank.C4_Kills)
				{
					YaRRVeteran::GiveMedal(p, 5);
				}
			}

			if(YaRRSettings::Medals::BeaconSniffer_Threshold != 0)
			{
				int BeaconSniffer_Threshold = (p->Rank.BeaconSniffer_Medals+1)*YaRRSettings::Medals::BeaconSniffer_Threshold;
				if(BeaconSniffer_Threshold <= p->Rank.Beacon_Kills)
				{
					YaRRVeteran::GiveMedal(p, 6);
				}
			}


			if(YaRRSettings::Awards::Killer_Threshold != 0)
			{
				int Killer_Threshold = (p->Rank.Killer_Awards+1)*YaRRSettings::Awards::Killer_Threshold;
				if(Killer_Threshold <= p->Rank.Player_Kills)
				{
					YaRRVeteran::GiveAward(p, 1);
				}
			}

			if(YaRRSettings::Awards::ArmsDestroyer_Threshold != 0)
			{
				int ArmsDestroyer_Threshold = (p->Rank.ArmsDestroyer_Awards+1)*YaRRSettings::Awards::ArmsDestroyer_Threshold;
				if(ArmsDestroyer_Threshold <= p->Rank.LightVehicle_Kills)
				{
					YaRRVeteran::GiveAward(p, 2);
				}
			}

			if(YaRRSettings::Awards::ArmorDestroyer_Threshold != 0)
			{
				int ArmorDestroyer_Threshold = (p->Rank.ArmorDestroyer_Awards+1)*YaRRSettings::Awards::ArmorDestroyer_Threshold;
				if(ArmorDestroyer_Threshold <= p->Rank.HeavyVehicle_Kills)
				{
					YaRRVeteran::GiveAward(p, 3);
				}
			}

			if(YaRRSettings::Awards::Demolition_Threshold != 0)
			{
				int Demolition_Threshold = (p->Rank.Demolition_Awards+1)*YaRRSettings::Awards::Demolition_Threshold;
				if(Demolition_Threshold <= p->Rank.Building_Kills)
				{
					YaRRVeteran::GiveAward(p, 4);
				}
			}

			if(YaRRSettings::Awards::Sabatage_Threshold != 0)
			{
				int Sabatage_Threshold = (p->Rank.Sabatage_Awards+1)*YaRRSettings::Awards::Sabatage_Threshold;
				if(Sabatage_Threshold <= p->Rank.C4_Kills)
				{
					YaRRVeteran::GiveAward(p, 5);
				}
			}

			if(YaRRSettings::Awards::BeaconSniffer_Threshold != 0)
			{
				int BeaconSniffer_Threshold = (p->Rank.BeaconSniffer_Awards+1)*YaRRSettings::Awards::BeaconSniffer_Threshold;
				if(BeaconSniffer_Threshold <= p->Rank.Beacon_Kills)
				{
					YaRRVeteran::GiveAward(p, 6);
				}
			}

			if(YaRRSettings::Awards::Medals_Threshold != 0)
			{
				int Medals_Threshold = (p->Rank.Medals_Awards+1)*YaRRSettings::Awards::Medals_Threshold;
				if(Medals_Threshold <= p->Rank.ArmorDestroyer_Medals+p->Rank.ArmsDestroyer_Medals+p->Rank.BeaconSniffer_Medals+p->Rank.Demolition_Medals+p->Rank.Killer_Medals+p->Rank.Sabatage_Medals)
				{
					YaRRVeteran::GiveAward(p, 7);
				}
			}

			if((GetLevel(p->Rank.VetScore) > p->Rank.Level) && p->Rank.Level < YaRRSettings::MaxVeteranLevel)
			{
				Promote(p);
			}
		}
	}
}

void YaRRVeteran::GiveMedal(Player *p, int Type)
{
	DLOG;
	if(Get_Player_Count() <= 1)
	{
		return;
	}
	if(Type == 1)
	{
		ConsoleInputF("msg %s recived the %s medal for killing %d player%s", p->Nick, YaRRSettings::Medals::Killer_Name, YaRRSettings::Medals::Killer_Threshold, YaRRSettings::Medals::Killer_Threshold == 1 ? "" : "s");
		PlaySound((void *)YaRRSettings::Medal_Killer_Sound, 2, 0, p->ID);
		p->Rank.Killer_Medals++;
	}
	else if(Type == 2)
	{
		ConsoleInputF("msg %s recived the %s medal for destroying %d light vehicle%s", p->Nick, YaRRSettings::Medals::ArmsDestroyer_Name, YaRRSettings::Medals::ArmsDestroyer_Threshold, YaRRSettings::Medals::ArmsDestroyer_Threshold == 1 ? "" : "s");
		PlaySound((void *)YaRRSettings::Medal_ArmsDestroyer_Sound, 2, 0, p->ID);
		p->Rank.ArmsDestroyer_Medals++;
	}
	else if(Type == 3)
	{
		ConsoleInputF("msg %s recived the %s medal for destroying %d heavy vehicle%s", p->Nick, YaRRSettings::Medals::ArmorDestroyer_Name, YaRRSettings::Medals::ArmorDestroyer_Threshold, YaRRSettings::Medals::ArmorDestroyer_Threshold == 1 ? "" : "s");
		PlaySound((void *)YaRRSettings::Medal_ArmorDestroyer_Sound, 2, 0, p->ID);
		p->Rank.ArmorDestroyer_Medals++;
	}
	else if(Type == 4)
	{
		ConsoleInputF("msg %s recived the %s medal for destroying %d building%s", p->Nick, YaRRSettings::Medals::Demolition_Name, YaRRSettings::Medals::Demolition_Threshold, YaRRSettings::Medals::Demolition_Threshold == 1 ? "" : "s");
		PlaySound((void *)YaRRSettings::Medal_Demolition_Sound, 2, 0, p->ID);
		p->Rank.Demolition_Medals++;
	}
	else if(Type == 5)
	{
		ConsoleInputF("msg %s recived the %s medal for disarming %d brick%s of C4", p->Nick, YaRRSettings::Medals::Sabatage_Name, YaRRSettings::Medals::Sabatage_Threshold, YaRRSettings::Medals::Sabatage_Threshold == 1 ? "" : "s");
		PlaySound((void *)YaRRSettings::Medal_Sabatage_Sound, 2, 0, p->ID);
		p->Rank.Sabatage_Medals++;
	}
	else if(Type == 6)
	{
		ConsoleInputF("msg %s recived the %s medal for disarming %d beacon%s", p->Nick, YaRRSettings::Medals::BeaconSniffer_Name, YaRRSettings::Medals::BeaconSniffer_Threshold, YaRRSettings::Medals::BeaconSniffer_Threshold == 1 ? "" : "s");
		PlaySound((void *)YaRRSettings::Medal_BeaconSniffer_Sound, 2, 0, p->ID);
		p->Rank.BeaconSniffer_Medals++;
	}
}

void YaRRVeteran::GiveAward(Player *p, int Type)
{
	DLOG;
	if(Get_Player_Count() <= 1)
	{
		return;
	}
	if(Type == 1)
	{
		ConsoleInputF("msg %s recived the %s award for killing %d player%s", p->Nick, YaRRSettings::Awards::Killer_Name, YaRRSettings::Awards::Killer_Threshold, YaRRSettings::Awards::Killer_Threshold == 1 ? "" : "s");
		PlaySound((void *)YaRRSettings::Award_Killer_Sound, 2, 0, p->ID);
		p->Rank.Killer_Awards++;
	}
	else if(Type == 2)
	{
		ConsoleInputF("msg %s recived the %s award for destroying %d light vehicle%s", p->Nick, YaRRSettings::Awards::ArmsDestroyer_Name, YaRRSettings::Awards::ArmsDestroyer_Threshold, YaRRSettings::Awards::ArmsDestroyer_Threshold == 1 ? "" : "s");
		PlaySound((void *)YaRRSettings::Award_ArmsDestroyer_Sound, 2, 0, p->ID);
		p->Rank.ArmsDestroyer_Awards++;
	}
	else if(Type == 3)
	{
		ConsoleInputF("msg %s recived the %s award for destroying %d heavy vehicle%s", p->Nick, YaRRSettings::Awards::ArmorDestroyer_Name, YaRRSettings::Awards::ArmorDestroyer_Threshold, YaRRSettings::Awards::ArmorDestroyer_Threshold == 1 ? "" : "s");
		PlaySound((void *)YaRRSettings::Award_ArmorDestroyer_Sound, 2, 0, p->ID);
		p->Rank.ArmorDestroyer_Awards++;
	}
	else if(Type == 4)
	{
		ConsoleInputF("msg %s recived the %s award for destroying %d building%s", p->Nick, YaRRSettings::Awards::Demolition_Name, YaRRSettings::Awards::Demolition_Threshold, YaRRSettings::Awards::Demolition_Threshold == 1 ? "" : "s");
		PlaySound((void *)YaRRSettings::Award_Demolition_Sound, 2, 0, p->ID);
		p->Rank.Demolition_Awards++;
	}
	else if(Type == 5)
	{
		ConsoleInputF("msg %s recived the %s award for disarming %d brick%s of C4", p->Nick, YaRRSettings::Awards::Sabatage_Name, YaRRSettings::Awards::Sabatage_Threshold, YaRRSettings::Awards::Sabatage_Threshold == 1 ? "" : "s");
		PlaySound((void *)YaRRSettings::Award_Sabatage_Sound, 2, 0, p->ID);
		p->Rank.Sabatage_Awards++;
	}
	else if(Type == 6)
	{
		ConsoleInputF("msg %s recived the %s award for disarming %d beacon%s", p->Nick, YaRRSettings::Awards::BeaconSniffer_Name, YaRRSettings::Awards::BeaconSniffer_Threshold, YaRRSettings::Awards::BeaconSniffer_Threshold == 1 ? "" : "s");
		PlaySound((void *)YaRRSettings::Award_BeaconSniffer_Sound, 2, 0, p->ID);
		p->Rank.BeaconSniffer_Awards++;
	}
	else if(Type == 7)
	{
		ConsoleInputF("msg %s recived the %s award for achieving %d medal%s", p->Nick, YaRRSettings::Awards::Medals_Name, YaRRSettings::Awards::Medals_Threshold, YaRRSettings::Awards::Medals_Threshold == 1 ? "" : "s");
		PlaySound((void *)YaRRSettings::Award_Medals_Sound, 2, 0, p->ID);
		p->Rank.Medals_Awards++;
	}
}

void YaRRVeteran::PlayerJoined(int ID)
{
	const char *PName = Get_Player_Name_By_ID(ID);
	Stacker<Row *> Result;
	Query(&Result, "SELECT COUNT(*) FROM Ranks WHERE Score >= (SELECT Score FROM Ranks WHERE Nick = '%q');", PName);
	if(Result.Empty() || strcmp(GetColumnData("COUNT(*)", (Result[0]->Columns)), "0") == 0)
	{
		Query(0, "INSERT INTO Ranks(Nick, Score) VALUES('%q', 0);", PName);
	}
	else
	{	
		int Rank = atoi(GetColumnData("COUNT(*)", (Result[0]->Columns)));
		DeleteResult(&Result);

		Query(&Result, "SELECT Score FROM Ranks WHERE Nick = '%q';", PName);
		float Score = (float)atof(GetColumnData("Score", Result[0]->Columns));
		DeleteResult(&Result);
		if(Score == 0)
		{
			delete []PName;
			return;
		}

		char Postfix[4];
		if(Rank % 10 == 1)
		{
			strcpy(Postfix, "st");
		}
		else if(Rank % 10 == 2)
		{
			strcpy(Postfix, "nd");
		}
		else if(Rank % 10 == 3)
		{
			strcpy(Postfix, "rd");
		}
		else
		{
			strcpy(Postfix, "th");
		}
		
		ConsoleInputF("msg %s is ranked %d%s with a score of %.0f points", PName, Rank, Postfix, Score);
	}

	delete []PName;
}

void YaRRVeteran::ObjectDamaged(int PlayerID, GameObject *obj, float Damage)
{
	float Points = 0;

	if(Is_Soldier(obj))
	{
		Points = Damage * RankInfo::Player_Damage_CoEfficient;
	}
	else if(Is_Vehicle(obj))
	{
		Points = Damage * RankInfo::Vehicle_Damage_CoEfficient;	
	}
	else if(Is_Building(obj))
	{
		Points = Damage * RankInfo::Building_Damage_CoEfficient;
	}
	else if(Is_Beacon(obj))
	{
		Points = Damage * RankInfo::Beacon_Damage_CoEfficient;
	}
	else if(Is_C4(obj))
	{
		Points = Damage * RankInfo::C4_Damage_CoEfficient;
	}

	Player *p = Find(PlayerID);
	p->Rank.RankScore += Points;
}

void YaRRVeteran::ObjectKilled(int PlayerID, GameObject *obj)
{
	float Points = 0;
	int Vet = 0;
	float Damage = (Commands->Get_Max_Health(obj) + Commands->Get_Max_Shield_Strength(obj)) * (float)0.25;

	if(Is_Soldier(obj))
	{
		Points = Damage * RankInfo::Player_Damage_CoEfficient;
		Vet = 2;
	}
	else if(Is_Vehicle(obj))
	{
		Points = Damage * RankInfo::Vehicle_Damage_CoEfficient;	
		Vet = 4;
	}
	else if(Is_Building(obj))
	{
		Points = Damage * RankInfo::Building_Damage_CoEfficient;
		Vet = 10;
	}
	else if(Is_Beacon(obj))
	{
		Points = Damage * RankInfo::Beacon_Damage_CoEfficient;
		Vet = 4;
	}
	else if(Is_C4(obj))
	{
		Points = Damage * RankInfo::C4_Damage_CoEfficient;
		Vet = 1;
	}

	Player *p = Find(PlayerID);
	p->Rank.RankScore += Points;
	p->Rank.VetScore += Vet;
}

void YaRRVeteran::Mapend()
{
	for(int i = 0; i < 128; i++)
	{
		Player *p = Players[i];
		if(p)
		{
			Query(0, "UPDATE Ranks SET Score = Score + %f WHERE Nick = '%q';", p->Rank.RankScore, p->Nick);
		}
	}
}

void YaRRVeteran::PlayerLeave(Player *p)
{
	Query(0, "UPDATE Ranks SET Score = Score + %f WHERE Nick = '%q';", p->Rank.RankScore, p->Nick);
}

void YaRRVeteran::Promote(Player *p)
{
	YaRRFunctions::ConsoleInputF("msg %s was promoted to %s!", p->Nick, YaRRSettings::GetPremotionName(p->Rank.Level));
	PPage(p->ID, "You have been promoted to %s!", YaRRSettings::GetPremotionName(p->Rank.Level));
	p->Rank.Level++;
}

int YaRRVeteran::GetLevel(int Score)
{
	return (int)sqrt((double)Score+12)-4;
}

int YaRRVeteran::GetScore(int Level)
{
	return (int)pow(double(Level+5), 2)-12;
}